﻿package com.robotcontroller.buaa.client;

import java.io.BufferedOutputStream;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.Inet4Address;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Calendar;
import java.util.Locale;
import java.util.Stack;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.Semaphore;

import org.apache.http.conn.util.InetAddressUtils;

import com.robotcontroller.buaa.client.RobotControlCommand.RobotDevIDInfor;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.text.AlteredCharSequence;
import android.text.format.DateFormat;
import android.util.Base64;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnLongClickListener;
import android.view.ViewGroup;
import android.view.Window;
import android.view.View.OnClickListener;
import android.view.inputmethod.EditorInfo;
import android.widget.AbsoluteLayout;
import android.widget.ArrayAdapter;
import android.widget.GridView;
import android.widget.ImageButton;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;


public class MainActivity extends Activity 
{
    // Debugging
    private static final String TAG = "cyy";
    private static final boolean D = true;
    
    private String serverIP;         //服务器IP
    private static final int httpPORT = 8080;            //服务器http服务的端口号
    private static final int scbtPORT = 5558;            //服务器转发蓝牙命令服务的端口号
    
    //和服务器http 8080连接标志
    private static boolean httpisconnected = false;
    //和服务器端口tcp 5558连接标志
    private static boolean socketbtconnected = false;
    
    //网络状态改变标志
    public final static int STATE_CONNECTED = 0;
    public final static int STATE_CONNECTING = 1;
    public final static int STATE_NONE = 2;
    public final static int  MESSAGE_NETSTATE_CHANGE = 5;
    
    //网络socket通信的消息类型
    public final static int MSG_MANULCONTROL = 8;
    public final static int MSG_AUTOCTL_TRACE = 9;
    
    //从服务器接受到机器人返回的协议命令标志和歇息命令的类型
    public final static int MESSAGE_ROBOTCMD_READ = 9;
    public final static int ROBOTCMD_READ_ID0 = 0;   //机器人传感器设备0的信息
    public final static int ROBOTCMD_READ_ID1 = 1;   //机器人传感器设备1的信息
    public final static int ROBOTCMD_READ_ID2 = 2;
    public final static int ROBOTCMD_READ_ID3 = 3;
    public final static int ROBOTCMD_READ_ID4 = 4;
    public final static int ROBOTCMD_READ_ID5 = 5;
    public final static int ROBOTCMD_READ_ID6 = 6;
    public final static int ROBOTCMD_READ_ID7 = 7;
    public final static int ROBOTCMD_READ_ID8 = 8;
    public final static int ROBOTCMD_READ_ID9 = 9;
 
   // private byte[] recvjpgbuf = new byte[1025*60];  //60KB缓冲区，接受jpeg帧
    private int imgWidth, imgHeight;  
    private Bitmap bitmap;            
    
    private SendCmdThread sendcmdthread;
    private HttpClientThread httpclientthread;
    //private RecvJpgDraw mrcjgpdrawthread;
    
    // Layout Views
    private TextView mTitleNetState;     //显示网络状态
    private TextView mTitleWorkState;    //显示工作状态，控制机器行走，巡线，环境建图等

	 AbsoluteLayout abslayoutbtns ;
	 LayoutInflater inflater;
    
    //机器人控制命令对象
    private RobotControlCommand robotcontroller = null;
    //机器人行为控制按钮定义
    private ImageButton mButton1;
    private ImageButton mButton2;
    private ImageButton mButton3;
    private ImageButton mButton4;
    private ImageButton mButton5;
    private ImageButton mButton6;
    private ImageButton mButton7;
    private ImageButton mButton8;
    private ImageButton mButtonStart;
    private ImageButton mButtonleft;
    private ImageButton mButtonright;
    private ImageButton mButtonup;
    private ImageButton mButtondown;
    
    private int gloangle = 45; //保存手机夹持机构的角度，改进，获取当前角度值
    //按钮的时间监听对象
    private MyButtonListener mButtonListener;            //长按事件处理
    private MyButtonOnClickListener mButtonOnClicklistener;  //短按事件处理
    
    //是否准备好给机器人发送命令的状态，初始为false
    //增加改进为获取机器人准备好状态
    //所以必须要先按start键，再按其他的案件
    private boolean isStart = false;
    

	private SurfaceView mSurfaceView;
	private SurfaceHolder mSurfaceHolder;
	
	//获取手机屏幕分辨率的类  
    private DisplayMetrics dm ;
    private int heightPix;
    private int widthPix;
    
    //环境建图用到的画布等
    private Bitmap newbdlgev;  
    private Canvas canvasdlgev ;  
    private Paint paitdlgev;  
    private Drawable drawable ;
	private int bitmapwidth;   //环境建图中的画图的宽度
	private int bitmapheight;   //环境建图中的画图的高度
	boolean isbdlgev = false;  //是否已经进入做图布局的标志
	boolean isonetime = true;
	private ImageView imgview; //画图所在的控件
	private Semaphore blgfevSem = null;
	private SendUlsDis sdulsdisthread = null; //向机器人按照角度发送超声波测距线程
	private int usdigree;        //超声波测距器测距的角度
	private String strdistance;  //角度和距离值，文本打印或者输出
	private double orgx = -1;   //环境做图中，保存前一次的坐标
	private double orgy = -1;   //环境做图中，保存前一次的坐标
	//private int perdegree = 0;  //每次测量角度量，范围为1度到359度，整数        
	
	//对话框
	private AlertDialog dialogline = null;  //巡线提示对话框
	private AlertDialog dialoginfdis = null; //红外短距测距提示对话框
	
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if(D) Log.e(TAG, "+++ ON CREATE +++");
       
        dm = new DisplayMetrics();  
        getWindowManager().getDefaultDisplay().getMetrics(dm);  
        
        heightPix = dm.heightPixels;
        widthPix = dm.widthPixels ;
        Log.i("cyy" , "screen definition,w:" + widthPix +" h:"+ heightPix  );
        //480*800，加载默认布局
        //320*480，加载布局320*480
        if(480==heightPix&&320==widthPix)
        {
        	setContentView(R.layout.main_480_320);
        	bitmapwidth = 320;
		    bitmapheight = 190;
        }
        else if(1024==heightPix&&600==widthPix)
        {
        	setContentView(R.layout.main_1024_600);
        	bitmapwidth = 600;
		    bitmapheight = 270;
        }
        else
        {
        	  setContentView(R.layout.main);
			  bitmapwidth = 480;
			  bitmapheight = 350;
        }
        
		abslayoutbtns = (AbsoluteLayout) findViewById(R.id.abslayoutbtns);
		inflater = LayoutInflater.from(this);
        
		isbdlgev = false;  //是否正在环境做图
		
		/*
		//环境做图的相关设置
        newbdlgev = Bitmap.createBitmap( bitmapwidth , bitmapheight , Config.ARGB_8888 );  
        drawable = new BitmapDrawable(newbdlgev); 
        canvasdlgev = new Canvas( newbdlgev );  
        paitdlgev = new Paint();  
        
        canvasdlgev.drawColor(Color.WHITE);      	        
        String familyName = "宋体";  
        Typeface font = Typeface.create(familyName, Typeface.BOLD);  
        paitdlgev.setColor(Color.RED);  
        paitdlgev.setTypeface(font);  
        paitdlgev.setTextSize(20); 
       */
		
         //机器人控制命令
         robotcontroller = new RobotControlCommand();
         
         mTitleNetState = (TextView)findViewById(R.id.textvidw_net_state);
         mTitleWorkState= (TextView)findViewById(R.id.textvidw_wrok_state);
         mTitleNetState.setText(R.string.titleNetNone);
         

       
       //设置预览控件
       mSurfaceView = (SurfaceView)this.findViewById(R.id.SurfaceView01); 
       mSurfaceHolder = mSurfaceView.getHolder();     
       mSurfaceHolder.addCallback(new MySurfaceCallBack());
       //mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);  //不适用于播放
       
       //mButtonStart.setVisibility(View.GONE);
    }
    
    
    class MySurfaceCallBack implements SurfaceHolder.Callback {  
  
        @Override  
        public void surfaceChanged(SurfaceHolder holder, int format, int width,  
                int height) {  
            Log.i("cyy", "surfaceview change");  
        }  
        @Override  
        public void surfaceCreated(SurfaceHolder holder) {  
            Log.i("cyy", "surfaceview create");  
             imgWidth = 480;  
             imgHeight = 320;                 
        }  
        @Override  
        public void surfaceDestroyed(SurfaceHolder holder) {  
            Log.i("cyy", "surfaceview destroy");  
        }  
    }  
    
    
    @Override
    public void onStart() {
        super.onStart();
        if(D) Log.e(TAG, "++ ON START ++");

    }

    @Override
    public synchronized void onResume() {
        super.onResume();
        if(D) Log.e(TAG, "+ ON RESUME +");

    }
  
    //短按事件处理
    private class MyButtonOnClickListener implements OnClickListener
    {
		@Override
		public void onClick(View v)
		{
			// TODO Auto-generated method stub
			if(socketbtconnected)  //socket连接之后
			{
				if(isStart)  //开始按钮启动之后
				{
					byte[] command = null;  //发送给机器人的命令	
					switch( v.getId() )
					{		   
							case R.id.buttonleft:
							{
								//按一次左转30度
								  byte id = 0x01;                //底盘的ID
								  byte[] cmdarg = {0x09 ,0x14};  //逆时针旋转0x14度，即20度	 
								                                 //09表示逆时针，0x14表示20读
								  command = robotcontroller.W_CMDtoRobot(id, cmdarg);
								  sendCommand(command , MSG_MANULCONTROL);	
								 break;
							}
							case R.id.buttonright:
							{
								//按一次右转30度
								  byte id = 0x01;                //底盘的ID
								  byte[] cmdarg = {0x0A ,0x14};  //顺时 针旋转0x14度，即20度	 
								                                 //0x0A表示逆时针，0x14表示20读
								  command = robotcontroller.W_CMDtoRobot(id, cmdarg);	
								  sendCommand(command , MSG_MANULCONTROL);	
								 break;
							}
							default:
							{
								
							}
					}
				}
			}
			else
			{
				Toast.makeText(MainActivity.this, "not connected to server:5558", Toast.LENGTH_LONG).show();
			}
		}
    }
     
    //长按事件处理
    private class MyButtonListener implements OnLongClickListener{
		@Override
		public boolean onLongClick(View v) {
			if(socketbtconnected) //与服务器5558端口TCP连接成功
			{
				byte[] command = null;  //发送给机器人的命令		
				switch( v.getId() )
				{
					case R.id.buttonStart:
					{
						   if(isStart)   
						   {
							  isStart = false;
							  //mButtonStart.setText("START");	
							  mButtonStart.setImageDrawable(
									            getResources().getDrawable(R.drawable.imgstart));    
							  
							  
							   //发送停止底盘运动命令						
							  byte id = 0x01;          //底盘的ID
							  byte[] cmdarg = {0x00};  //停止底盘			  
							  command = robotcontroller.W_CMDtoRobot(id, cmdarg);
							  sendCommand(command , MSG_MANULCONTROL);					  
						   }else
						   {//底盘正在活跃，此时才可以可以使用方向按钮
							  isStart = true;
							  mButtonStart.setImageDrawable(
				                        getResources().getDrawable(R.drawable.imgpause)); 
							  return true; //此处添加这个，表示此行不发送命令！！！！
						   }
					    break;
					}
					//根据转向比较慢的特点，转向使用短按事件处理
                    
    				case R.id.buttonleft:
    				{
    					//按一次左转30度
    					  byte id = 0x01;                //底盘的ID
    					  byte[] cmdarg = {0x09 ,0x14};  //逆时针旋转0x14度，即20度	 
    					                                 //09表示逆时针，0x14表示20读
    					  command = robotcontroller.W_CMDtoRobot(id, cmdarg);
    					  sendCommand(command , MSG_MANULCONTROL);	
    					 break;
    				}
    				case R.id.buttonright:
    				{
    					//按一次右转30度
    					  byte id = 0x01;                //底盘的ID
    					  byte[] cmdarg = {0x0A ,0x14};  //顺时 针旋转0x14度，即20度	 
    					                                 //0x0A表示逆时针，0x14表示20读
    					  command = robotcontroller.W_CMDtoRobot(id, cmdarg);	
    					  sendCommand(command , MSG_MANULCONTROL);	
    					 break;
    				}
    				
					default:
					{
						//8个方向行走按钮的事件处理
						if(isStart)
						{
							//调用
							RepeatOnClickEve(v.getId());
						}
					}
				}//endwicth
			}else
			{
				Toast.makeText(MainActivity.this, "not connected to server:5558", Toast.LENGTH_LONG).show();
			}
			
			return true;
		}
    	
    }
    
    //当buttonb被按下的时候，调用该函数，8个方向的长按加速
    //继续增加，让速度递增！
    public void RepeatOnClickEve(final int viewID)
    {
        final Timer timer = new Timer();
        TimerTask timertask = new TimerTask(){
           byte speed = 0;  //speed值最大为0x64即为100
           int angle = 45;   //手机夹持机构角度，45读到135读。即0x2D到0x87H 
            @Override
            public void run()
            {
            	//Log.i("cyy" , "timetast running....");
                 if(findViewById(viewID).isPressed())
                    { 
                	 if(speed >= 0x64)
                	 {
                		 speed = 0x64; 
                	 }
                	 else
                	 {
                		 speed = (byte) (speed + 0x05);
                	 }       
                	 
                	// Log.i("cyy" , "In timetast ,ImageButton is pressed!");
                	   //按钮还被按着，加速。。。
	         			byte[] command = null;  //发送给机器人的命令		
	        			switch( viewID)
	        			{
	        			
	        				case R.id.button1:
	        				{
	        					 //Log.i("cyy" , "In timetast ,ImageButton 1 is pressed!");
	        					//对应Dir3方向，手机夹持设备的位置
	        					  byte id = 0x01;                //底盘的ID
	        					  byte[] cmdarg = {0x03 ,speed};  //沿Dir3方向20H速度前进		  
	        					  command = robotcontroller.W_CMDtoRobot(id, cmdarg);	
	        					  //Log.i("cyy" , "button1 is pressed,will send cmd");
	        				}
	        				break;
	        				case R.id.button2:
	        				{
	        					//对应Dir2方向
	        					  byte id = 0x01;                //底盘的ID
	        					  byte[] cmdarg = {0x02 ,speed};  //沿Dir2方向10H速度前进		  
	        					  command = robotcontroller.W_CMDtoRobot(id, cmdarg);	
	        				}
	        				break;
	        				case R.id.button3:
	        				{
	        					//对应Dir1方向
	        					  byte id = 0x01;                //底盘的ID
	        					  byte[] cmdarg = {0x01 ,speed};  //沿Dir1方向10H速度前进		  
	        					  command = robotcontroller.W_CMDtoRobot(id, cmdarg);	
	        				}
	        				break;
	        				case R.id.button4:
	        				{
	        					//对应Dir8方向
	        					  byte id = 0x01;                //底盘的ID
	        					  byte[] cmdarg = {0x08 ,speed};  //沿Dir8方向10H速度前进		  
	        					  command = robotcontroller.W_CMDtoRobot(id, cmdarg);	
	        				}	
	        				break;
	        				case R.id.button5:
	        				{
	        					//对应Dir7方向
	        					  byte id = 0x01;                //底盘的ID
	        					  byte[] cmdarg = {0x07 ,speed};  //沿Dir7方向10H速度前进		  
	        					  command = robotcontroller.W_CMDtoRobot(id, cmdarg);	
	        				}	
	        				break;
	        				case R.id.button6:
	        				{
	        					//对应Dir6方向
	        					  byte id = 0x01;                //底盘的ID
	        					  byte[] cmdarg = {0x06 ,speed};  //沿Dir6方向10H速度前进		  
	        					  command = robotcontroller.W_CMDtoRobot(id, cmdarg);	
	        				}	
	        				break;				
	        				case R.id.button7:
	        				{
	        					//对应Dir5方向
	        					  byte id = 0x01;                //底盘的ID
	        					  byte[] cmdarg = {0x05 ,speed};  //沿Dir5方向10H速度前进		  
	        					  command = robotcontroller.W_CMDtoRobot(id, cmdarg);	
	        				}	
	        				break;
	        				case R.id.button8:
	        				{
	        					//对应Dir4方向
	        					  byte id = 0x01;                //底盘的ID
	        					  byte[] cmdarg = {0x04 ,speed};  //沿Dir4方向10H速度前进		  
	        					  command = robotcontroller.W_CMDtoRobot(id, cmdarg);	
	        				}	
	        			    break;	
	        			    
	    					case R.id.btcamdirdown:   //手机夹持机构 45到135度！！！确定！！
	    					{
	    						angle = gloangle; //获取全局变量的值    					
	    						if(angle < 45)
	    						{
	    							angle = 45;
	    						}
	    						
	    						
	    						  //Log.i("cyy" , "anggle:" + angle);
	    						  
	    						   //发送夹持机构0度					
	    						  byte id = 0x02;          //手机夹持机构的ID
	    						  byte anglebyte = (byte)(angle&0x000000FF);
	    						  byte[] cmdarg = {anglebyte};  //0度  。。0x00到0x87			  
	    						  command = robotcontroller.W_CMDtoRobot(id, cmdarg);
	    						  
	    						angle = angle - 5;
	    						gloangle = angle;
	    						break;
	    					}
	    					case R.id.btcamdirup:
	    					{
	    						  angle = gloangle;
	    						 // byte tmp = (byte) 0x87;
	    						 /*
	    						  * 0x87即是135，一个字节，java只有有符号数
	    						  * 故，java把0x87这个字节当成负数了
	    						  * 所以比较好的方法是用int处理计算，然后转回为byte
	    						  */
	    						  if(angle > 135)  
	    						  {
	    							  angle = 135;
	    						  }
	    						 
	    						  
	    						  //Log.i("cyy" , "anggle:" + angle);
	    						//发送夹持机构0度					
	    						  byte id = 0x02;          //手机夹持机构的ID
	    						  byte anglebyte = (byte)(angle&0x000000FF);
	    						  byte[] cmdarg = {anglebyte};  //80度  。。0x00到0x87			  
	    						  command = robotcontroller.W_CMDtoRobot(id, cmdarg);
	    						  
	    						  angle = angle + 5;
	    						  gloangle = angle;
	    						break;
	    					}
	    					
	        			    
	        			}//endofswitch
	        	        //发送命令
	                     if(isStart)  sendCommand(command , MSG_MANULCONTROL);		         
                }
                  else
                    timer.cancel();
            }//endofrun()
    };   
    
       timer.schedule(timertask, 0, 500);  //0毫秒后执行，500毫秒执行一次
    }
    
    /*
     * 处理自定义线程发送的异步信息
     */
    private final Handler myHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) 
        {
            switch (msg.what) 
            {
            case MESSAGE_NETSTATE_CHANGE:     //网络状态的改变
                if(D) Log.i(TAG, "MESSAGE_STATE_CHANGE: " + msg.arg1);
                switch (msg.arg1) 
                {
	                case STATE_CONNECTED:
	                 Toast.makeText(getApplicationContext(), "成功连接服务器",
	                               Toast.LENGTH_SHORT).show();
	                 mTitleNetState.setText(R.string.titleNetConneted);
	                    break;
	                case STATE_CONNECTING:
		                 Toast.makeText(getApplicationContext(), "正在连接服务器",
	                               Toast.LENGTH_SHORT).show();
		                 mTitleNetState.setText(R.string.titleNetConnectting);
	                    break;
	                case STATE_NONE:
		                 Toast.makeText(getApplicationContext(), "服务器连接断开",
	                               Toast.LENGTH_SHORT).show();
		                 mTitleNetState.setText(R.string.titleNetNone);
		                 
		                 
	                    break;
                }
                break;
                
            case MESSAGE_ROBOTCMD_READ:     //接受到机器人传感器信息
            {
            	switch(msg.arg1)
            	{
	            	case ROBOTCMD_READ_ID0:    //机器人传感器设备0的信息
	            	{
	  	        	  final TextView distancetv = new TextView(MainActivity.this);
	  	        	  
	  	        	  if(null != dialogline)
	  	        	  {
		  	        	  dialogline.cancel(); // 关闭弹出的正在巡线的提示的对话框
		  	        	  dialogline = null;
	  	        	  }
		        	  
		        	   distancetv.setText("巡线完毕");  //正在巡线和巡线完成通知
			        	new AlertDialog.Builder(MainActivity.this)
			        	.setTitle("机器人巡线")
			        	.setIcon(null)
			        	.setView(distancetv)
			        	.setPositiveButton(R.string.strconfirm,null)
			        	.show();
	            		
			        	mTitleWorkState.setText(R.string.titleCmdLineDone);
	            		break;
	            	}
	            	case ROBOTCMD_READ_ID1:
	            	{
	            		break;
	            	}
	            	case ROBOTCMD_READ_ID2:
	            	{
	            		break;
	            	}
	            	case ROBOTCMD_READ_ID3:
	            	{
		      
		          		  byte[] val = (byte[])msg.obj ;
	            		  int vallen = (int)msg.arg2 ;
	            		  String strInfdis1 = "";
	            		  String strInfdis2 = "";

	            		  strInfdis1 = strInfdis1 + ByteToUnint(val[0]);
	            		  strInfdis2 = strInfdis2 + ByteToUnint(val[1]);
		            	  
		  	        	  final TextView distancetv = new TextView(MainActivity.this);
			        	   distancetv.setText("前方距离为:\r\n"
			        			               + strInfdis1+"\r\n"
			        			               + strInfdis2);   //返回红外的值
			        	   if(null != dialoginfdis)
			        	   {
			        		   dialoginfdis.cancel(); //关闭弹出的红外短距测距提示对话框
			        		   dialoginfdis = null;
			        	   }
			        
			        	   AlertDialog dialogRFID = new AlertDialog.Builder(MainActivity.this)
				        	.setTitle("红外短距测距")
				        	.setIcon(null)
				        	.setView(distancetv)
				        	.setPositiveButton(R.string.strconfirm,null)
				        	.show();
			        	
	            		break;
	            	}
	            	case ROBOTCMD_READ_ID4:
	            	{
	            		break;
	            	}
	            	case ROBOTCMD_READ_ID5:
	            	{
	            		break;
	            	}
	            	case ROBOTCMD_READ_ID6:
	            	{
	            		break;
	            	}
	            	case ROBOTCMD_READ_ID7:
	            	{
	            		break;
	            	}
	            	case ROBOTCMD_READ_ID8:   //RFID定位
	            	{
	            	 // String strRFIDval = new String( (byte[])msg.obj , 0 , msg.arg2 );
	            	 
	          		  byte[] val = (byte[])msg.obj ;
            		  int vallen = (int)msg.arg2 ;
            		  String strRFIDval = "";
            		  
            		  for(int i=0 ; i<vallen ; i++)
            		  {
            			  strRFIDval = strRFIDval + ByteToUnint(val[i]);
            		  }
            		  //+ (int)val[0] +","+ (int)val[1];
	            	  
	  	        	  final TextView distancetv = new TextView(MainActivity.this);
		        	   distancetv.setText("RFID值为:"+strRFIDval);   //返回ID卡的ID号
		        	   AlertDialog dialogRFID = new AlertDialog.Builder(MainActivity.this)
			        	.setTitle("RIDF定位")
			        	.setIcon(null)
			        	.setView(distancetv)
			        	.setPositiveButton(R.string.strconfirm,null)
			        	.show();
		        	
		        	   
	            		break;
	            	}
	            	case ROBOTCMD_READ_ID9:
	            	{
	            		//超声波测距仪返回的距离值
	            		/*BB  FF  04  09  XH  XL  FF
	            		 * 由高位字节XH和地位字节XL共同组成
	            		 */
	            		           		
	            			  byte[] val = (byte[])msg.obj ;
		            		  int vallen = (int)msg.arg2 ;
		            		  String strDis = "";            		  
		            		 
		            		  int distance = 256*ByteToUnint(val[0]) + ByteToUnint(val[1]);
		            		  double degree = usdigree;

		            		  /*
		            		  Log.i("cyy" , "Ultrasonic ranging"
			            		  		+",distance:"+distance
			            		  		+",degree:"+ degree);
		            		  */
		            		  
		            		  if(distance < 1)
		            		  {
		            			  distance = 1;
		            		  }
		            		  if(distance > 400)
		            		  {
		            			 distance = 400;  
		            		  }
		            		  
		            		   
		            		  /*
		            		   * 画图，坐标系，画布的左上角为(0,0)，右下角为(bitmapwidth ,bitmapheight )
		            		   * 
		            		   * 根据距离distance和角度imgdegree做图
		            		   */
		            		  
		            		 double r;
		            		 
		            		// r = Math.sqrt(bitmapheight*bitmapheight + bitmapwidth*bitmapwidth);
		            		 
		            		 
		            		 if(bitmapwidth <= bitmapheight )
		            		 {
		            			 r =  ((double)bitmapwidth/2/400)*(double)distance ;
		            		 }
		            		 else
		            		 {
		            			 r =  ((double)bitmapheight/2/400)*(double)distance ;
		            		 }
		            		 
		            		 
		            		  double x , y;
		            		  /*
		            		  x = (bitmapwidth)/2 + r * Math.sin(degree/180*Math.PI);
		            		  y = (bitmapheight)/2 - r * Math.cos(degree/180*Math.PI);
		            		  
		            		  
		            		  Log.i("cyy" , "degree:" + degree +"°"
		            				  + "sin(degree):" + Math.sin(degree/180*Math.PI)
		            				  + "cos(degree):" + Math.cos(degree/180*Math.PI));
		            		  */
		            		  
		            		  
		            		  x = (bitmapwidth)/2 - r * Math.sin(degree/180*Math.PI);
		            		  y = (bitmapheight)/2 - r * Math.cos(degree/180*Math.PI);
		            		  
		            		  /*
		            		  Log.i("cyy" , "Eenviroment drawing, "
			            		  		+",distance:"+distance
			            		  		+",degree:"+ degree
			            		  		+",r:"+r
			            		  		+",x:"+(int)x
			            		  		+",y:"+(int)y);
		            		 */

		     				
		            		if(isbdlgev)  //只在环境做图界面下启作用
		            		{
			            		//要考虑到线程对象sdulsdisthread是否还在 
			            		blgfevSem.release();
			            		 
			     				if(null != strdistance )
			     				{
				            		  strdistance = strdistance + "\r\n"
			            		  		+"角度:"+ degree + "度，"
			            		  		+"距离:"+distance + "厘米";
			     				}
			     				
			     				if(degree == 359)
			    				{
			    					blgfevSem.drainPermits();
			    					
			  	  	        	    final TextView textview = new TextView(MainActivity.this);				  	        	  					        	  
			  	  	        	   textview.setText(strdistance);  //正在巡线和巡线完成通知
						        	new AlertDialog.Builder(MainActivity.this)
						        	.setTitle("360度全向测距")
						        	.setIcon(null)
						        	.setView(textview)
						        	.setPositiveButton(R.string.strconfirm,null)
						        	.show();
			    				}
		            			


		                        /*
		                         * 终于对齐了坐标，最终坐标由newbdlgev和imgview的大小决定
		                         * 设定newbdlgev和imgview大小一样，都是宽480，搞360，
		                         * 则，下面做图函数的参数的坐标位置即为在480*360的位置
		                         */
		                        canvasdlgev.drawText("环境建图功能，正在建图", 0, 30, paitdlgev);  		                        
		                        		                        		                        
		           
		        	            //canvasdlgev.drawCircle(bitmapwidth/2 , bitmapheight/2 , (int)r/2 , paitdlgev);
		                        //根据角度和距离计算坐标
		                        canvasdlgev.drawCircle(bitmapwidth/2 , bitmapheight/2 , 5 , paitdlgev); //表示机器人的位置
		                        
		                        if(orgx== -1 && orgx== -1) //表示开始画第一个坐标
		                        {
		                        	orgx = x;
		                        	orgy = y;
		                        }
		                        canvasdlgev.drawLine((float) orgx , (float) orgy , (float)x , (float)y, paitdlgev);
		        	            imgview.setBackgroundDrawable(drawable);
		        	            
			        	      	orgx = x;
			            		orgy = y;  //保存前一次的坐标
		            	        
		            		}
		            		
	            		  
	            		
	            		break;
	            	}	            	
            	}
            	
            	break;
            }
 
            }
        }
    };

    @Override
    public synchronized void onPause() {
        super.onPause();
        if(D) Log.e(TAG, "- ON PAUSE -");
    }

    @Override
    public void onStop() {
        super.onStop();
        if(D) Log.e(TAG, "-- ON STOP --");
    }


    @Override
    public void onDestroy() {
        super.onDestroy();
    }

    
//退出软件的时候确认选择      	
private void ExitOptionsDialog()
{
	  AlertDialog.Builder builder = new AlertDialog.Builder(this); 
	  builder.setMessage("是否退出程序") 
	         .setCancelable(false) 
	         .setPositiveButton("确定", new DialogInterface.OnClickListener() { 
	             public void onClick(DialogInterface dialog, int id) { 
	            	 try {
	            		 if(socketbtconnected) sendcmdthread.cancel();
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					
	            	 android.os.Process.killProcess(android.os.Process.myPid());
	             } 
	         }) 
	         .setNegativeButton("取消", new DialogInterface.OnClickListener() { 
	             public void onClick(DialogInterface dialog, int id) { 
	                  dialog.cancel(); 
	             } 
	         }); 
	  AlertDialog alert = builder.create();
	  alert.show();
}

//监听按键动作函数
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
	//按下键盘上返回按钮
	if(keyCode == KeyEvent.KEYCODE_BACK){
		ExitOptionsDialog();
		return true;
	}else{		
		return super.onKeyDown(keyCode, event);
	}
}


    private void sendCommand(byte[] command , int commandtype) 
    {
    	if(null != sendcmdthread)
    	{
            sendcmdthread.writeInt(commandtype);
    		sendcmdthread.write(command, 0, command.length);
    	}
    	
    }
    
    //创建menu按键菜单
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.option_menu, menu);
        return true;
    }
    
//menu按键菜单的选择函数
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) 
        {
	        case R.id.menuBTCmu:
	        {
	        	return true;
	        }
	        case R.id.connectserver:
	        {	
	            final EditText edittextIP = new EditText(MainActivity.this);
	        	new AlertDialog.Builder(MainActivity.this)
	        	.setTitle(R.string.strinputserverIP)
	        	.setIcon(null)
	        	.setView(edittextIP)
	        	.setPositiveButton(R.string.strconfirm,new DialogInterface.OnClickListener(){
	                @Override
	                public void onClick(DialogInterface dialog, int which) {
	                    
	                  
	                    String temp;
	                    temp = edittextIP.getText().toString();
	                    if( !InetAddressUtils.isIPv4Address(temp))
	                    {  //IP地址合法
	                    	Log.i("cyy" , "unligal IPV4 address");
	                    	new AlertDialog.Builder(MainActivity.this)
	                    	         .setTitle(R.string.strunligalIPadd).show();
	                    }else
	                    {   //合法的IP地址
	                    	Log.i("cyy" , "input the ip: "+temp);
	                    	serverIP = temp;
	                        sendcmdthread = new SendCmdThread(serverIP , scbtPORT , myHandler);
	                        sendcmdthread.start();
	                    	
	                        httpclientthread = new HttpClientThread(serverIP, httpPORT, myHandler);
	                        httpclientthread.start();

	                    }
	                    //finish();
	                }                
	            })
	        	.setNegativeButton(R.string.strcancel, null)
	        	.show();
	        	
	        	return true;
	        }
	        
	        case R.id.menucontrolRbt:   //控制机器人，主要功能是加载控制按钮
	        {
	        	
	        	abslayoutbtns.removeAllViews();     
	        	AbsoluteLayout abslayout2;
	            if(480==heightPix && 320==widthPix)
	            {
	            	//320*240分辨率下的控制按钮布局
	            	abslayout2 = (AbsoluteLayout) inflater.inflate(
							R.layout.absbtn_480_320, null).findViewById(R.id.abslayoutbtns);
	            	abslayoutbtns.addView(abslayout2);
	            }
	            else if(1024==heightPix&&600==widthPix)
	            {
	            	//1024*600分辨率下的控制按钮布局
	            	abslayout2 = (AbsoluteLayout) inflater.inflate(
							R.layout.absbtn_1024_600, null).findViewById(R.id.abslayoutbtns);
	            	abslayoutbtns.addView(abslayout2);
	            }
	            else
	            {
	            	//800*480分辨率下的控制按钮布局
	            	abslayout2 = (AbsoluteLayout) inflater.inflate(
							R.layout.absbtnslayout , null).findViewById(R.id.abslayoutbtns);
	            	abslayoutbtns.addView(abslayout2);
	            }	            	        		        
	        	
	            isbdlgev = false;  //是否正在环境做图
	            
	            //机器人行为控制按钮。。。设置长按的事件监听
	            mButton1 = (ImageButton)findViewById(R.id.button1);
	            mButton2 = (ImageButton)findViewById(R.id.button2);
	            mButton3 = (ImageButton)findViewById(R.id.button3);
	            mButton4 = (ImageButton)findViewById(R.id.button4);
	            mButton5 = (ImageButton)findViewById(R.id.button5);
	            mButton6 = (ImageButton)findViewById(R.id.button6);
	            mButton7 = (ImageButton)findViewById(R.id.button7);
	            mButton8 = (ImageButton)findViewById(R.id.button8);
	            mButtonStart = (ImageButton)findViewById(R.id.buttonStart);
	            mButtonleft = (ImageButton)findViewById(R.id.buttonleft);
	            mButtonright = (ImageButton)findViewById(R.id.buttonright);
	            mButtonup = (ImageButton)findViewById(R.id.btcamdirup);
	            mButtondown = (ImageButton)findViewById(R.id.btcamdirdown);
	           

	            
	            if(isStart)
	            {
					mButtonStart.setImageDrawable(
				            getResources().getDrawable(R.drawable.imgpause));  
	            }
	            else
	            {
					mButtonStart.setImageDrawable(
				            getResources().getDrawable(R.drawable.imgstart));  
	            }
	            
	            
	            //监听按钮长按事件
	            mButtonListener = new MyButtonListener();
	            //监听按钮的短按事件
	            mButtonOnClicklistener = new MyButtonOnClickListener();
	            
	            //设置按钮的长按事件处理
	            mButton1.setOnLongClickListener(mButtonListener);
	            mButton2.setOnLongClickListener(mButtonListener);
	            mButton3.setOnLongClickListener(mButtonListener);
	            mButton4.setOnLongClickListener(mButtonListener);
	            mButton5.setOnLongClickListener(mButtonListener);
	            mButton6.setOnLongClickListener(mButtonListener);
	            mButton7.setOnLongClickListener(mButtonListener);
	            mButton8.setOnLongClickListener(mButtonListener);
	            mButtonStart.setOnLongClickListener(mButtonListener);
	            mButtondown.setOnLongClickListener(mButtonListener);
	            mButtonup.setOnLongClickListener(mButtonListener);
	            mButtonleft.setOnLongClickListener(mButtonListener);
	            mButtonright.setOnLongClickListener(mButtonListener);
	            
	            //设置左转和右转的短按事件处理
	            mButtonleft.setOnClickListener(mButtonOnClicklistener);
	            mButtonright.setOnClickListener(mButtonOnClicklistener);
	            
	            if(null != sdulsdisthread)
	            {
	            	sdulsdisthread.cancel();
	            	sdulsdisthread = null;
	            }
	            

	            
	            
	            break;
	        }
	        case R.id.menuStObjTra:  //开启人物跟踪
	        {
	        	byte[] cmd = new byte[1];
	        	cmd[0] = 1;
	        	sendCommand(cmd, MSG_AUTOCTL_TRACE);
	        	break;
	        }
	        case R.id.menustopobjttra: //关闭人物跟踪
	        {
	        	byte[] cmd = new byte[1];
	        	cmd[0] = 0;
	        	sendCommand(cmd, MSG_AUTOCTL_TRACE);
	        	
				  
				   //发送停止底盘运动命令						
				  byte id = 0x01;          //底盘的ID
				  byte[] cmdarg = {0x00};  //停止底盘			  
				  byte[] command = robotcontroller.W_CMDtoRobot(id, cmdarg);
				  sendCommand(command , MSG_MANULCONTROL);	
				  
	        	break;
	        }
	        case R.id.Envbltfigure:  //环境建图功能，每次旋转的度数和当前进度，
	        	                     //大概需要90秒，自定义一个布局，画图和进度条
	        {	   	        	
	            final EditText edittextPerdegree = new EditText(MainActivity.this);
	        	new AlertDialog.Builder(MainActivity.this)
	        	.setTitle("请输入每次测量的分量（1到359）")
	        	.setIcon(null)
	        	.setView(edittextPerdegree)
	        	.setPositiveButton(R.string.strconfirm,new DialogInterface.OnClickListener(){
	                @Override
	                public void onClick(DialogInterface dialog, int which) {	                  
	                    String temp;
	                    temp = edittextPerdegree.getText().toString();
	                    int tempint=0 ;
	                    
	                    try
	                    {
	                    	 tempint = Integer.parseInt(temp);
	                    }catch (NumberFormatException e)
	                    {  //参数格式错误
	                    	  new AlertDialog.Builder(MainActivity.this)
               	                      .setTitle("请输入整数（1到359）").show();
	                    	  
						}
	                   	                    
	                    if( tempint>1 && tempint<359)
	                    {  //合法的参数
	                    	 int perdegree = tempint;  //每次测量角度量，范围为1度到359度，整数          
	                    	  
	                      	/*
	          	        	 * 环境建图功能基本设计：
	          	        	 * 1、切换布局
	          	        	 * 2、发送建图命令，0度处测距
	          	        	 * 3、开启线程专门去画图？貌似不用，而且比较麻烦
	          	        	 * 3、直接在myHandler中，接受到超声波测距结果，然后就去画图！？先这样，然后再改进
	          	        	 * 接受到0度处的值，然后再发送30度。接受30°的值，然后再发送60°......知道330°！
	          	        	 */
	          	        	
	          	        	abslayoutbtns.removeAllViews();        	
	          	        	AbsoluteLayout imgviewlayout ;

	          	        	 if(480==heightPix&&320==widthPix)
	          	        	 {
	          	        		//320*240分辨率下的控制环境做图布局
	          	        		 imgviewlayout = (AbsoluteLayout) inflater.inflate(
	          		 						R.layout.imgview_480_320 , null).findViewById(R.id.imgviewlayout);	
	          	        		 
	          		 				abslayoutbtns.addView(imgviewlayout);
	          		 				//bitmapwidth = 320;
	          		 				//bitmapheight = 200;

	          	        	 }
	          	        	 else if(1024==heightPix&&600==widthPix)
	          	        	 {
		          	        		//1024*600分辨率下的控制环境做图布局
		          	        		 imgviewlayout = (AbsoluteLayout) inflater.inflate(
		          		 						R.layout.imgview_1024_600 , null).findViewById(R.id.imgviewlayout);	
		          	        		 
		          		 				abslayoutbtns.addView(imgviewlayout);
		          		 				//bitmapwidth = 600;
		          		 				//bitmapheight = 270;
		          	         }
	          	        	 else
	          	        	 {
	          	        		 //800*240分辨率下的环境做图布局
	          	        		 imgviewlayout = (AbsoluteLayout) inflater.inflate(
	          	 						R.layout.imageview , null).findViewById(R.id.imgviewlayout);	
	          	        		 
	          	 				abslayoutbtns.addView(imgviewlayout);
	          	 				//bitmapwidth = 480;
	          	 				//bitmapheight = 360;
	          	        	 }
	          	        	 
	          	        	 isbdlgev = true;  //是否正在环境做图
	          	        	 
	          	        	imgview = (ImageView)findViewById(R.id.ImgView01);
	          				int imgviewWidth = imgview.getWidth();
	          				int imgviewHeight = imgview.getHeight();
	          				Log.i("cyy" , "imgview height:"+imgviewHeight
	          						+" imgview width:"+imgviewWidth);	//为什么都是0呢 ？？？
	          				
	          				//环境做图的相关设置
	          		        newbdlgev = Bitmap.createBitmap( bitmapwidth , bitmapheight , Config.ARGB_8888 );  
	          		        drawable = new BitmapDrawable(newbdlgev); 
	          		        canvasdlgev = new Canvas( newbdlgev );  
	          		        paitdlgev = new Paint();  
	          		        
	          		        canvasdlgev.drawColor(Color.WHITE);      	        
	          		        String familyName = "宋体";  
	          		        Typeface font = Typeface.create(familyName, Typeface.BOLD);  
	          		        paitdlgev.setColor(Color.RED);  
	          		        paitdlgev.setTypeface(font);  
	          		        paitdlgev.setTextSize(20); 
	                 				
	          				
	          			   if(null != blgfevSem)
	          			   {
	          				   blgfevSem.drainPermits();  //释放所有的锁，线程sdulsdisthread自然就获取锁执行，退出
	          			   }
	          			   blgfevSem = null;
	          			   blgfevSem = new Semaphore(0);
	          			   blgfevSem.release();            //唤醒发送超声波测距线程
	          			   
	          			   /*
	          				if(null != sdulsdisthread)  
	          				{
	          					sdulsdisthread.cancel();
	          				}
	          				*/
	          			   
	          				sdulsdisthread = new SendUlsDis(perdegree , blgfevSem); //向机器人按照角度发送超声波测距线程
	          				sdulsdisthread.start();
	          				
	          				//使用信号量同步，开启线程，需要传递一个值，一个角度值，一个信号量
	          				

	          		        strdistance = null;
	          		        strdistance = new String();
	          				  
	          		        
	                    }else
	                    {  //不合法参数
	                    	  new AlertDialog.Builder(MainActivity.this)
       	                      .setTitle("请输入整数（1到359）").show();
	                    	  
	                    }
	                }                
	            })
	        	.setNegativeButton(R.string.strcancel, null)
	        	.show();     	
	
	        	return true;
	        }
	        
	        case R.id.Infrareddistance:  //红外短距测距
	        {
	        	if(socketbtconnected)
	        	{
		        	  final TextView distancetv = new TextView(MainActivity.this);
		        	   distancetv.setText("正在测距...");
	        		   dialoginfdis =new AlertDialog.Builder(MainActivity.this)
			        	.setTitle("红外短距测距")
			        	.setIcon(null)
			        	.setView(distancetv)
			        	//.setPositiveButton(R.string.strconfirm,null)
			        	.show();
			        	
			        	//发送红外短距测距命令
			        	  byte[] command = null;
						  byte id = 0x03;                 //巡线的ID
						  byte[] cmdarg = null;          //参数		  
						  command = robotcontroller.R_CMDtoRobot(id, cmdarg);	
						  sendCommand(command , MSG_MANULCONTROL);	
						  
						  //mTitleWorkState.setText(R.string.title); 
	        	}
	        	else
	        	{
	        		Toast.makeText(MainActivity.this, "not connected to server:5558", 
                            Toast.LENGTH_LONG).show();
	        	}

	        	
	        	return true;
	        }
	        
	        case R.id.menulinepatrol:   //巡线
	        {
	        	if(socketbtconnected)
	        	{
		        	  final TextView distancetv = new TextView(MainActivity.this);
		        	  
		        	  distancetv.setText("正在巡线...");  //正在巡线和巡线完成通知
		        	  dialogline = new AlertDialog.Builder(MainActivity.this)
			        	.setTitle("机器人巡线功能")
			        	.setIcon(null)
			        	.setView(distancetv)
			        	//.setPositiveButton(R.string.strconfirm,null)
			        	.show();
			        	
						  //发送巡线命令
			        	  byte[] command = null;
						  byte id = 0x00;                 //巡线的ID
						  byte[] cmdarg = {0x01};  //沿Dir4方向10H速度前进		  
						  command = robotcontroller.W_CMDtoRobot(id, cmdarg);	
						  sendCommand(command , MSG_MANULCONTROL);	
						  
						  mTitleWorkState.setText(R.string.titleCmdLine);
						  
						  //dialogline.cancel();
						  
	        	}
	        	else
	        	{
	        		Toast.makeText(MainActivity.this, "not connected to server:5558", 
	        				                              Toast.LENGTH_LONG).show();
	        	}

	        	
	        	return true;
	        }
	        
	        case R.id.rfidLoc:         //RFID定位
	        {

		        	if(socketbtconnected)
		        	{
			        	  final TextView distancetv = new TextView(MainActivity.this);
			        	  
			        	  distancetv.setText("启动RFID定位功能");  //正在巡线和巡线完成通知
			        	  AlertDialog dialogRFID = new AlertDialog.Builder(MainActivity.this)
				        	.setTitle("RFID定位")
				        	.setIcon(null)
				         	.setView(distancetv)
				        	.setPositiveButton(R.string.strconfirm,null)
				        	.show();
				        	
						//机器人识别到RFID卡，就自动给手机发送该卡的值，不需要命令机器人	  
					    //mTitleWorkState.setText(R.string.titleCmdLine);
							  
		        	}
		        	else
		        	{
		        		Toast.makeText(MainActivity.this, "not connected to server:5558", 
		        				                              Toast.LENGTH_LONG).show();
		        	}
	        	   
	        	return true;
	        }

        }
        return false;
    }

/*
 * socket连接请求线程，连接服务器，端口5558
 * 向服务器发送控制机器人命令
 */
   public class SendCmdThread extends Thread
   {
	  	private DataOutputStream mdos;
    	private DataInputStream mdis;
    	private int mport;               //服务器端口
    	private String mIP;              //服务器IP
    	private Socket mcsocket;                
        private byte[] recvcmdbuf = new byte[100];  //接受服务器返回的信息缓冲区
        private int recvlen;                        //每次接受服务器返回信息长度
        private Handler mhandler;
    	
    	public SendCmdThread(String strIp ,int nport , Handler nhandler)
    	{
    		mhandler = nhandler;
    		mport = nport;
    		mIP = strIp;
    	}
    	
    	
    	@Override
    	public void run()
    	{
    		try 
    		{
    		    mhandler.obtainMessage(MESSAGE_NETSTATE_CHANGE
    		    		, STATE_CONNECTING , 0).sendToTarget();
    		    
				mcsocket = new Socket(mIP , mport);
				
				Log.i("cyy" , "connected to server");
				
				socketbtconnected = true;
    		    mhandler.obtainMessage(MESSAGE_NETSTATE_CHANGE
    		    		, STATE_CONNECTED , 0).sendToTarget();
			} catch (IOException e) 
			{
				//连接服务器异常，通知UI连接服务器失败，
				e.printStackTrace();
    		    mhandler.obtainMessage(MESSAGE_NETSTATE_CHANGE
    		    		, STATE_NONE , 0).sendToTarget();
				return ;
			}
			
			
			try 
			{
				mdos = new DataOutputStream(mcsocket.getOutputStream());
				mdis = new DataInputStream(mcsocket.getInputStream());
			} catch (IOException e) 
			{
				//抛出异常？ 会是哪种原因呢？查！
				socketbtconnected =false;
    		    mhandler.obtainMessage(MESSAGE_NETSTATE_CHANGE
    		    		, STATE_NONE , 0).sendToTarget();
				e.printStackTrace();
				try 
				{
					mcsocket.close();
				} catch (IOException e1) 
				{
					e1.printStackTrace();
				}
				return ;
			}
			
			
			//注意，发送端不能发送的太频繁，否则CPU占用率太高，导致另一个httpserver太卡
			
			while(true)
			{
				try
				{
					recvlen = mdis.readInt();
					if(recvlen >= 100)
						recvlen = 100;
					mdis.readFully(recvcmdbuf, 0, recvlen);
					//将接受的命令传送机器人去分析
					
					//Log.i("cyy" , "recive cmd from server , cmd is");
				    /*
					for(int i=0; i<recvlen ; i++)
						Log.i("cyy" , " "+recvcmdbuf[i]);
					*/
					
	                RobotDevIDInfor rbtIDInfor = new RobotDevIDInfor();
	                rbtIDInfor = robotcontroller.ParseRobotCMD(recvcmdbuf, recvlen);
	                
					//int ID = robotcontroller.ParseRobotCMD(recvcmdbuf, recvlen);
					
	                //Log.i("cyy" , "ID:" + rbtIDInfor.ID);
	    		    mhandler.obtainMessage(MESSAGE_ROBOTCMD_READ
	    		    		, rbtIDInfor.ID , rbtIDInfor.IDInforLen , rbtIDInfor.IDInfor).sendToTarget();
	    		    
	 
	                
	                //OK，能正确得到数据，
	    		    /*
	                for(int i=0; i<rbtIDInfor.IDInforLen ; i++)
	                {
	                	k("cyy" , "val[" + i +"]"+rbtIDInfor.IDInfor[i]);
	                }
	                */
	    		    
	                /*
                    String strval = new String(rbtIDInfor.IDInfor , 0 , rbtIDInfor.IDInforLen);                   
                    Log.i("cyy" , "val:"+strval);
	                */
	                
	                
					sleep(100);
					if(mcsocket.isClosed())  //貌似反应很慢，应该开启另一个端连接？
						break;
					
				} catch (IOException e) 
				{
					Log.i("cyy" , "read error, will close socket");
					socketbtconnected =false;
	    		    mhandler.obtainMessage(MESSAGE_NETSTATE_CHANGE
	    		    		, STATE_NONE , 0).sendToTarget();
					try 
					{
						mcsocket.close();
						break;
					} catch (IOException e1) 
					{
						e1.printStackTrace();
					}
					
					e.printStackTrace();
					break;
				} catch (InterruptedException e) 
				{
					e.printStackTrace();
				}
			}//endwhile
             
			
			try 
			{
    		    mhandler.obtainMessage(MESSAGE_NETSTATE_CHANGE
    		    		, STATE_NONE , 0).sendToTarget();
				socketbtconnected = false;
				mdos.close();
				mdis.close();
				mcsocket.close();

			} catch (IOException e) 
			{
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
	
    	}//end_run()
    	
    	
    	public synchronized void writeInt(int val)
    	{
    		if(mcsocket.isConnected()&&socketbtconnected)
        		//if(socketbtconnected)
        		{
        			//Log.i("cyy" , "write to server");
        			try 
        			{
        				mdos.writeInt(val);
    				} catch (IOException e) 
    				{
    					e.printStackTrace();
    				}
        		}else
        		{
        		    mhandler.obtainMessage(MESSAGE_NETSTATE_CHANGE
        		    		, STATE_NONE , 0).sendToTarget();
        		}
    	}
    	
    	/*
    	 * 发送数据
    	 */
    	public synchronized void write(byte[] sendbuf , int offset , int len)
    	{
    		if(mcsocket.isConnected()&&socketbtconnected)
    		{
    			//Log.i("cyy" , "write to server");
    			try 
    			{
    				mdos.writeInt(sendbuf.length);
					mdos.write(sendbuf, offset, len);
				} catch (IOException e) 
				{
					e.printStackTrace();
				}
    		}else
    		{
    		    mhandler.obtainMessage(MESSAGE_NETSTATE_CHANGE
    		    		, STATE_NONE , 0).sendToTarget();
    		}
    	}
    	
    	public void cancel() throws IOException
    	{
			socketbtconnected = false;
			mdos.close();
			mdis.close();
			mcsocket.close();
    	}
    	
   }//endofclass
   
   /*
    * HTTP clien形式，解析服务器返回的HTTP响应信息
    * 
    * 功能：
    * 1、请求连接httpserver，连接成功后，发送http请求 GET JPG....
    * 2、接受HTTPSERVER返回的HTTP响应信息，提出出来jpeg帧，并且刷新播放到surfaceview上去
    * 
    * 暂时只接受解析Content-Type: multipart/x-mixed-replace这样的类型，其他的后期改进
    * 主要流程：
    * 1、接受解析HTTP响应的信息头，暂时就提取boundary字段，该值是Jpeg帧之间的划分标志。
    *    后期HTTPSERVER完善之后，再增加解析其他的字段
    * 2、根据boundary的值，从jpeg流中分离出单帧
    */
   class HttpClientThread extends Thread
   {
	  	private DataOutputStream mdos;
    	private DataInputStream mdis;
    	private int mhttpserverport;               //服务器端口
    	private String mhttpserverIP;              //服务器IP
    	private Socket mcsocket;                
        private byte[] headerbuf = new byte[1024*2];     //2KB接受服务器返回的信息缓冲区
        private byte[] recvjpgbuf = new byte[1024*300];   //50KB，接受httpserver返回的jpeg混合流
        private Handler mhandler;
    	
    	public HttpClientThread(String strIp ,int nport , Handler nhandler)
    	{
    		mhandler = nhandler;
    		mhttpserverport = nport;
    		mhttpserverIP = strIp;
    	}
    	
    	
    	@Override
    	public void run()
    	{
    		
    		//连接HTTPSERVER
    		try 
    		{
    		    mhandler.obtainMessage(MESSAGE_NETSTATE_CHANGE
    		    		, STATE_CONNECTING , 0).sendToTarget();
    		    
				mcsocket = new Socket(mhttpserverIP , mhttpserverport);
				Log.i("cyy" , "connected to server");			
				socketbtconnected = true;
    		    mhandler.obtainMessage(MESSAGE_NETSTATE_CHANGE
    		    		, STATE_CONNECTED , 0).sendToTarget();
			} catch (IOException e) 
			{
				//连接服务器异常，通知UI连接服务器失败，
				e.printStackTrace();
    		    mhandler.obtainMessage(MESSAGE_NETSTATE_CHANGE
    		    		, STATE_NONE , 0).sendToTarget();
				return ;
			}
			
			//初始化输入流和输出流
			try 
			{
				mdos = new DataOutputStream(mcsocket.getOutputStream());
				mdis = new DataInputStream(mcsocket.getInputStream());
			} catch (IOException e) 
			{
				clean();
				return;
			}
			
			
			//发送HTTP请求 ， Get ./jpg 
			Log.i("cyy" , "write a HTTPREQUEST to the httpserver");
			
			String ID = "cyy";
			String Key = "1234";
			String IDKey = ID + ":" + Key;   
			//base64加密
			String encodeIDKey = Base64.encodeToString(IDKey.getBytes() , 0);
			
			String strHTTPHeader = "GET /jpeg-stream HTTP/1.0\r\n"
			                     + "Authorization: Basic " + encodeIDKey + "\r\n";
			
            try 
            {
				mdos.write(strHTTPHeader.getBytes());
				mdos.flush();
			} catch (IOException e2) 
			{
				clean();
				return ;
			}
			
			//提取HTTP响应信息，重点是提取字段Content-Type: multipart/x-mixed-replace;
			//提取字段boundary
			int recvlen;
			try
			{
				recvlen = mdis.read(headerbuf);
			}catch (Exception e) 
			{
				clean();
				return;
			}
			if(-1 == recvlen)
			{
				Log.i("cyy" , "read error!");
				clean();
			}
			
			//分析headerbuf？？？重点和难点！！！
			int beginstr, endstr;
			//String temp = headerbuf.toString();
			String temp = new String(headerbuf , 0 , recvlen);
			Log.i("cyy" , "recive the HTTPRESPONSE from httpserever");
			Log.i("cyy" , "HTTPRESPONSE is "+temp);
			String boundary;
			beginstr = temp.indexOf("boundary=");
	        endstr = temp.indexOf("\r\n", beginstr);
	        boundary = temp.substring(beginstr + "boundary=".getBytes().length  ,  endstr);
	        Log.i("cyy" , "boundary: "+boundary);
			
			long frames = 0; //接受的帧的总数
			long begintime = System.currentTimeMillis();
			long endtime;
	        
	        //从jpeg流中提取每帧jpeg，然后刷新到surfaceview上面去
			//先一行行的读取，直到遇到字段Content_Length:获取jpeg帧的长度，提取出来然后使用readFully()
			String line;
			int framelen;
			
			
			//播放Jpeg用到对象
			int canwidth, canheight;
	        if(480==heightPix&&320==widthPix)
	        {

	        	canwidth = 320;
	        	canheight = 240;

	        }
	        else if(1024==heightPix&&600==widthPix)
	        {
	        	canwidth = 600;
	        	canheight = 470;
	        }
	        else
	        {
	        	canwidth = 480;
	        	canheight = 320;
	        }
	        
            Bitmap bmImg = null;
            Bitmap btmnew = null;
            Rect rect = new Rect(0 , 0 , canwidth , canheight);
            Canvas canvas = null;
            Paint  paint = new Paint();
  		    //旋转Bitmap用到的矩阵
            Matrix matrix = new Matrix(); 
		    matrix.postRotate(90);
            
	        while(true)
			{
				try
				{
					
					line = mdis.readLine();
					while( -1 == line.indexOf("Content_Length:") )
					{
						line = mdis.readLine();
						//Log.i("cyy" , "read line: "+line);
					}
	
					beginstr = line.indexOf("Content_Length:");
				    
				     // 找了崩溃异常的原因了，endstr的值为-1，因为readLine()结果没有"\r\n"
					temp = line.substring(beginstr+"Content_Length:".getBytes().length  
							               , line.getBytes().length);   //次数抛出异常！！！！
					
					temp = temp.trim();  //清除空格，否则转换崩溃
					framelen = Integer.parseInt(temp);
					//Log.i("cyy" , "frame len is "+framelen +" B");  
					if(framelen >= recvjpgbuf.length)
					{
						framelen = recvjpgbuf.length;
						Log.i("cyy" , "jpeg length is too large, maybe some errors");
					}
					
				    mdis.readLine(); //清除"/r/n"，，可能有多行"\r\n"，需要清除，注意
					mdis.readFully(recvjpgbuf, 0, framelen);					

					
					canvas = mSurfaceHolder.lockCanvas(rect);                	
	                if(canvas != null)  //必须判断的，如果隐藏到后台，c就空
	                {
	                
	                	bmImg = BitmapFactory.decodeByteArray(recvjpgbuf, 0, framelen);

		                int imgwidth = bmImg.getWidth();
		                int imgheight= bmImg.getHeight();
		                
		                //320*240
		                int left = Math.abs((canwidth-imgwidth)/2);   //240
		                
		                //240*320
		                //int left = Math.abs((canwidth-imgheight)/2);   //240
		                int top = 0;  //320
		                //原样居中播放
		                canvas.drawBitmap(bmImg, left , top ,paint);
		  		               
		                /*//旋转90度
		               //使用矩阵和Bitmap创建新的Bitmap对象，旋转Bitmap，速度较慢
		    		    btmnew = Bitmap.createBitmap(bmImg ,  0,  0, 
		    		    		                            bmImg.getWidth(), bmImg.getHeight(), 
		    		    		                            matrix, true);
		                canvas.drawBitmap(btmnew, left , top , paint);
		                */		                
		                
                        mSurfaceHolder.unlockCanvasAndPost(canvas);// 更新屏幕显示内容  
                        bmImg = null;  //手动，引用置空，释放对象。
                        btmnew = null;
                        canvas = null;
	                }     
	                
					
	                //计算下，socket接受并且播放刷新的 帧率
	                //在服务器第一次被连接的情况下，帧率也是16，偶尔是25，
	                frames++;
					if(0 == frames%50)
					{
						endtime = System.currentTimeMillis();
						Log.i("cyy" , "frame rate is "+ frames/((endtime-begintime)/1000)+" pf" );
					}
	                
					if(mcsocket.isClosed())  //貌似反应很慢，应该开启另一个端连接？
						break;
					
				} catch (IOException e) 
				{
					Log.i("cyy" , "read error, will close socket");
					socketbtconnected =false;
	    		    mhandler.obtainMessage(MESSAGE_NETSTATE_CHANGE
	    		    		, STATE_NONE , 0).sendToTarget();
					try 
					{
						mcsocket.close();
						break;
					} catch (IOException e1) 
					{
						e1.printStackTrace();
					}
					
					e.printStackTrace();
					break;
				}
			}//endwhile
             
			clean();
			
	
    	}//end_run()
    	
    	void clean()
    	{
			try 
			{
			    mhandler.obtainMessage(MESSAGE_NETSTATE_CHANGE
			    		, STATE_NONE , 0).sendToTarget();
				socketbtconnected = false;
				mdos.close();
				mdis.close();
				mcsocket.close();
	
			} catch (IOException e) 
			{
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
    	}
    	
   }
   
   /*
    *发送环境建图命令线程，根据每次测量角度的频率来发送命令 
    *目前存在一个bug，生成多个该类的匿名对象，造成死锁，信号量只有一个全局的。
    *所以当切换到其他界面或者其他或者重复点击环境建图时候，应该销毁该变量
    */
   private class SendUlsDis extends Thread
   {
	   int ndegree;
	   Semaphore semaphore;
	  // boolean isrunning;
	   public SendUlsDis(int nd , Semaphore sema)
	   {
		  ndegree = nd;
		  semaphore = sema;
		  //isrunning = false;
	   }
	   
	   @Override
	   public void run()
	   {
			   
   		   for(int i=0; i<=360/ndegree ; i++) //发送360/ndegree次
			   {
				   try
				   {
					  semaphore.acquire();
				   } catch (InterruptedException e) 
					{
						// TODO Auto-generated catch block
						e.printStackTrace();
						//isrunning = false;
					}
				   //isrunning = true;
				  
		        	//发送超声波测距命令
	               /*
	                * AA FF 05 09 00 AH AL FF  
	                * 超声波传感器旋转至AH*256+AL角度，
	                * 读取该角度对应的距离，单位厘米，有效距离1~400厘米。
	                * （0 <= AH*256+AL < 360）
	                */
		        	  byte[] command = null;
					  byte id = 0x09;                               //超声波测距仪的ID
					  //如果ndegree*i的值大于或者等于360度，则取模

					  int degree = (ndegree*i)%360;  //degree用两个字节发送，值不会超过360，2个字节足够
					  if(i == (360/ndegree) )
					  {
						  degree = 359;
					  }
					  byte hdegree = (byte) ((degree>>8)&0x000000FF);          //degree第2位字节，从低位到高位
					  byte ldegree = (byte) (degree&0x000000FF);             //degree第1位字节
					 /*
					  Log.i("cyy" , "Environment built figure,"
							  +" degree:"+degree
							  +",hdegree:"+hdegree
							  +",ldegree:"+ldegree);
                      */
					  byte[] cmdarg = {hdegree , ldegree};  //参数，如果需要测大于255度如何？		  
					  command = robotcontroller.R_CMDtoRobot(id, cmdarg);	
					  sendCommand(command , MSG_MANULCONTROL);	
					  
					  usdigree = degree;  //做图的时候需要usdigree
			   }//endfor		   
   		   
			   //isrunning = false;
				   
   		    Log.i("cyy" , "the thread of sending supersonic distance will be closed");
	   }//endrun()
	   
	   void cancel()
	   {
		   semaphore.drainPermits(); //恢复所有的信号量
	   }
	  

   }
   
   /*
    * 将字节转换成无符号的整形数字
    * 例如0xf9，不转换为-7，转换后位249
    */
   public int ByteToUnint(byte byteval)
   {
   	int intval=0;
   	for(int i=0; i<=7 ; i++)
   	{
   		if( (byteval & (byte)Math.pow(2, i)) != 0)
   		{
   			intval = (int) (intval +  Math.pow(2, i));
   		}
   	}
   	return intval;
   }
   
 
}


